const phantom = require('phantom');
const cheerio = require('cheerio');
const fs = require("fs");
const csv = require('fast-csv');


// 爬取页面地址,第一页
const URL_PREFIX = "https://list.jd.com/list.html?cat=737,794,880&page="
const URL_SUFFIX = "&stock=0&sort=sort_rank_asc&trans=1&JL=4_7_0#J_main";


const Pa = async() => {
    const instance_getnum = await phantom.create(['--ignore-ssl-errors=yes', '--load-images=no']);
    const page_getnum = await instance_getnum.createPage();
    await page_getnum.open(URL_PREFIX + "1" + URL_SUFFIX);
    const listhref = [];
    //禁用详细页面的javascript以提高速度，所以以下三个内容必须从列表页读取了，故定义数组保存
    const list价格 = [];
    const list累计评价 = [];
    const list选购指数 = [];

    var csvStream = csv
        .createWriteStream({
            headers: true
        })
        .transform(function (row) {
            return {
                名称: row.a,
                价格: row.b,
                累计评价: row.c,
                选购指数: row.d,
                品牌: row.e,
                系列: row.f,
                型号: row.g,
                颜色: row.h,
                类别: row.i,
                自动化程度: row.j,
                显示方式: row.k,
                控制方式: row.l,
                开门方式: row.m,
                排水方式: row.n,
                电机类型: row.o,
                脱水功能: row.p,
                防缠绕: row.q,
                儿童安全锁: row.r,
                预约功能: row.s,
                夜间洗: row.t,
                中途添衣: row.u,
                洗涤转速: row.v,
                电辅加热烘干: row.w,
                电辅加热洗涤: row.x,
                自动断电: row.y,
                排水阀漏水保护: row.z,
                进水阀漏水保护: row.aa,
                其它: row.ab,
                智能断电记忆: row.ac,
                能效等级: row.ad,
                洗净比: row.ae,
                洗衣程序: row.af,
                "洗涤容量（kg）": row.ag,
                "洗涤功率（W）": row.ah,
                脱水转速: row.ai,
                干衣功能: row.aj,
                "脱水容量（kg）": row.ak,
                "脱水功率（W）": row.al,
                "烘干容量（kg）": row.am,
                "烘干功率（W）": row.an,
                脱水转速: row.ao,
                水温调节范围: row.ap,
                箱体材质: row.aq,
                内筒材质: row.ar,
                电源规格: row.as,
                "产品尺寸（深×宽×高）mm": row.at,
                "包装尺寸（深x宽x高）mm": row.au,
                "产品重量（kg）": row.av,
                节能等级: row.aw,
                特性: row.ax,
            };
        }),
        writableStream = fs.createWriteStream("京东洗衣机信息.csv");

    writableStream.on("finish", function () {
        console.log("全部数据抓取完毕！");
    });
    await csvStream.pipe(writableStream);
    await page_getnum.on('onResourceRequested', true, function (requestData) {});
    const content = await page_getnum.property('content');
    const tmp$ = cheerio.load(content);
    var pagenumhtml = tmp$('.p-skip').html();
    pagenumhtml = cheerio.load(pagenumhtml);
    var PAGETOTALNUM = pagenumhtml('b').text();
    await page_getnum.close();
    await instance_getnum.exit();
    var page, pageitem;
    for (var l = 0; l < PAGETOTALNUM; l++) {
        console.log("开始读取第" + (l + 1) + "页列表信息")
        const instance = await phantom.create(['--ignore-ssl-errors=yes', '--load-images=no']);
        page = await instance.createPage();
        var status = await page.open(URL_PREFIX + (l + 1) + URL_SUFFIX);
        while (status != "success") {
            await pageitem.close();
            console.log("网页暂时打不开，重试中..")
            status = await page.open(URL_PREFIX + (l + 1) + URL_SUFFIX);
        }
        const content = await page.property('content');
        const $ = await cheerio.load(content);
        //找所有的list
        await $('.gl-item').each(function (i, elem) {
            const li = cheerio.load($(this).html());
            listhref[i] = "http:" + li(".comment").attr("href");
            if (li('.js_ys').html() != null) {
                list价格[i] = li('.js_ys').text().replace("¥", "");
            }
            if (li('.comment').html() != null) {
                list累计评价[i] = li('.comment').text();
            }
            if (li('.buy-score').html() != null) {
                list选购指数[i] = li('.buy-score').text().replace("选购指数", "");
            }
        });
        console.log("读取第" + (l + 1) + "页列表信息成功")
        //循环读取每一个具体的网页循环读取每一个具体的网页
        for (var i = 2; i < listhref.length; i++) {


            if (listhref[i] != "http:undefined") {
                var Ptable_item = [];
                var finaldata = {
                    名称: "",
                    价格: "",
                    累计评价: "",
                    选购指数: "",
                    品牌: "",
                    系列: "",
                    型号: "",
                    颜色: "",
                    类别: "",
                    自动化程度: "",
                    显示方式: "",
                    控制方式: "",
                    开门方式: "",
                    排水方式: "",
                    电机类型: "",
                    脱水功能: "",
                    防缠绕: "",
                    儿童安全锁: "",
                    预约功能: "",
                    夜间洗: "",
                    中途添衣: "",
                    洗涤转速: "",
                    电辅加热烘干: "",
                    电辅加热洗涤: "",
                    自动断电: "",
                    排水阀漏水保护: "",
                    进水阀漏水保护: "",
                    其它: "",
                    智能断电记忆: "",
                    能效等级: "",
                    洗净比: "",
                    洗衣程序: "",
                    "洗涤容量（kg）": "",
                    "洗涤功率（W）": "",
                    脱水转速: "",
                    干衣功能: "",
                    "脱水容量（kg）": "",
                    "脱水功率（W）": "",
                    "烘干容量（kg）": "",
                    "烘干功率（W）": "",
                    脱水转速: "",
                    水温调节范围: "",
                    箱体材质: "",
                    内筒材质: "",
                    电源规格: "",
                    "产品尺寸（深×宽×高）mm": "",
                    "包装尺寸（深x宽x高）mm": "",
                    "产品重量（kg）": "",
                    节能等级: "",
                    特性: ""
                }
                pageitem = await instance.createPage();
                pageitem.setting('javascriptEnabled', "false");
                status = await pageitem.open(listhref[i]);
                console.log("开始爬取：", listhref[i])

                while (status != "success") {
                    status = await pageitem.open(listhref[i]);
                    await pageitem.close();
                    console.log("网页暂时打不开，重试中..")
                    status = await pageitem.open(listhref[i]);
                }

                await pageitem.on('onResourceRequested', true, function (requestData) {});
                const dcontent = await pageitem.property('content');
                detailcontent = await cheerio.load(dcontent);
                await pageitem.close();
                if (detailcontent(".ellipsis").html() != null) {
                    finaldata.名称 = detailcontent(".ellipsis").text();
                    finaldata.价格 = list价格[i];
                    finaldata.累计评价 = list累计评价[i];
                    finaldata.选购指数 = list选购指数[i];

                    //会有没有详细信息的情况
                    if (detailcontent("div[class=Ptable]").html() != null) {
                        //找到 规格与包装下的有内容
                        detailcontent = cheerio.load(detailcontent("div[class=Ptable]").html());
                        //检出 主体、功能、规格、特性四个内容，有时候特性是没有的，这样用循环读取，下一步可能为3也可能为4
                        await detailcontent('div[class=Ptable-item]').each(function (deatili, elem) {
                            Ptable_item[deatili] = $(this).html();
                        });
                        console.log("读取基本数据成功");
                        // 循环处理三（四）个内容，按dt<->dd读取，希望京东的dt是统一的
                        for (var k = 0; k < Ptable_item.length; k++) {
                            detailcontent = cheerio.load(Ptable_item[k]);
                            detailcontent(".Ptable-tips").remove();
                            detailcontent("h3").remove();
                            var datalistdd = [];
                            var datalistdt = [];

                            await detailcontent("dd").each(function (im, elem) {
                                datalistdd[im] = detailcontent(this).text();
                            });
                            await detailcontent("dt").each(function (im, elem) {
                                datalistdt[im] = detailcontent(this).text();
                            });
                            for (var im = 0; im < datalistdd.length; im++) {
                                finaldata[datalistdt[im]] = datalistdd[im];
                            }
                        }
                    }
                }

            } else { //全球购不太一样
                finaldata.名称 = detailcontent(".parameter2").children().first().text()
                finaldata.价格 = list价格[i];
                finaldata.累计评价 = list累计评价[i];
                finaldata.选购指数 = list选购指数[i];

                var Ptable_item = [];
                await detailcontent("th").remove();
                var tmp = [];
                detailcontent(".Ptable").find('td').each(function (i, elem) {
                    tmp[i] = detailcontent(this).text();
                });
                for (var d = 0; d < tmp.length; d += 2) {
                    finaldata[tmp[d]] = tmp[d + 1];
                }
            }
            await csvStream.write({
                a: finaldata['名称'],
                b: finaldata['价格'],
                c: finaldata['累计评价'],
                d: finaldata['选购指数'],
                e: finaldata['品牌'],
                f: finaldata['系列'],
                g: finaldata['型号'],
                h: finaldata['颜色'],
                i: finaldata['类别'],
                j: finaldata['自动化程度'],
                k: finaldata['显示方式'],
                l: finaldata['控制方式'],
                m: finaldata['开门方式'],
                n: finaldata['排水方式'],
                o: finaldata['电机类型'],
                p: finaldata['脱水功能'],
                q: finaldata['防缠绕'],
                r: finaldata['儿童安全锁'],
                s: finaldata['预约功能'],
                t: finaldata['夜间洗'],
                u: finaldata['中途添衣'],
                v: finaldata['洗涤转速'],
                w: finaldata['电辅加热烘干'],
                x: finaldata['电辅加热洗涤'],
                y: finaldata['自动断电'],
                z: finaldata['排水阀漏水保护'],
                aa: finaldata['进水阀漏水保护'],
                ab: finaldata['其它'],
                ac: finaldata['智能断电记忆'],
                ad: finaldata['能效等级'],
                ae: finaldata['洗净比'],
                af: finaldata['洗衣程序'],
                ag: finaldata['洗涤容量（kg）'],
                ah: finaldata['洗涤功率（W）'],
                ai: finaldata['脱水转速'],
                aj: finaldata['干衣功能'],
                ak: finaldata['脱水容量（kg）'],
                al: finaldata['脱水功率（W）'],
                am: finaldata['烘干容量（kg）'],
                an: finaldata['烘干功率（W）'],
                ao: finaldata['脱水转速'],
                ap: finaldata['水温调节范围'],
                aq: finaldata['箱体材质'],
                ar: finaldata['内筒材质'],
                as: finaldata['电源规格'],
                at: finaldata['产品尺寸（深×宽×高）mm'],
                au: finaldata['包装尺寸（深x宽x高）mm'],
                av: finaldata['产品重量（kg）'],
                aw: finaldata['节能等级'],
                ax: finaldata['特性'],
            });
            await console.log("写入第" + (l * 60 + i + 1) + "条数据");
        }
        await instance.exit();
    }
    await csvStream.end();
}

Pa();